package com.bt7274.service.impl;

import com.bt7274.mapper.UserDailyCheckInMapper;
import com.bt7274.mapper.*;
import com.bt7274.pojo.*;
import com.bt7274.pojo.bo.*;
import com.bt7274.pojo.vo.*;
import com.bt7274.service.PermanentPromotionService;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bt7274.enums.PermanentPromotionType;
import com.bt7274.exception.BusinessException;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @BelongsProject: bt7274-back
 * @BelongsPackage: com.bt7274.service.impl
 * @Author: Galland
 * @CreateTime: 2025-06-14
 * @Description: 常驻服务活动实现
 * @Version: 1.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PermanentPromotionServiceImpl implements PermanentPromotionService {

    private final UserDailyCheckInMapper checkInMapper;
    private final UserMapper userMapper;
    private final UserExpMapper userExpMapper;
    private final UserMilestoneRecordMapper userMilestoneRecordMapper;
    private final BtTransactionMapper transactionMapper;
    private final UserActivityProgressMapper activityProgressMapper;
    @Override
    @Transactional
    public UserCheckInVO dailyCheckIn(UserCheckInBO checkInBO) {
        String userId = checkInBO.getUserId();
        LocalDate today = LocalDate.now();

        // 验证用户
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 检查今天是否已签到
        QueryWrapper<UserDailyCheckIn> todayWrapper = new QueryWrapper<>();
        todayWrapper.eq("user_id", userId).eq("check_in_date", today);
        UserDailyCheckIn todayCheckIn = checkInMapper.selectOne(todayWrapper);

        if (todayCheckIn != null) {
            // 已签到，返回签到信息
            return buildCheckInVO(userId, todayCheckIn, false);
        }

        // 检查昨天是否签到（判断连续性）
        LocalDate yesterday = today.minusDays(1);
        QueryWrapper<UserDailyCheckIn> yesterdayWrapper = new QueryWrapper<>();
        yesterdayWrapper.eq("user_id", userId).eq("check_in_date", yesterday);
        UserDailyCheckIn yesterdayCheckIn = checkInMapper.selectOne(yesterdayWrapper);

        int consecutiveDays = 1;
        if (yesterdayCheckIn != null) {
            consecutiveDays = yesterdayCheckIn.getConsecutiveDays() + 1;
        }

        // 计算奖励
        int dailyReward = PermanentPromotionType.DAILY_LOGIN.getBaseReward();
        int consecutiveReward = PermanentPromotionType.calculateConsecutiveLoginReward(consecutiveDays);
        int milestoneReward = PermanentPromotionType.getConsecutiveMilestoneReward(consecutiveDays);
        int totalReward = dailyReward + consecutiveReward + milestoneReward;

        // 创建签到记录
        UserDailyCheckIn checkIn = new UserDailyCheckIn();
        checkIn.setId(UUID.randomUUID().toString().replace("-", ""));
        checkIn.setUserId(userId);
        checkIn.setCheckInDate(today);
        checkIn.setConsecutiveDays(consecutiveDays);
        checkIn.setReward(totalReward);
        checkIn.setCheckInTime(LocalDateTime.now());
        checkInMapper.insert(checkIn);

        // 发放奖励
        StringBuilder rewardDesc = new StringBuilder("每日签到奖励：");
        rewardDesc.append(dailyReward).append(" BT币");

        if (consecutiveReward > 0) {
            rewardDesc.append("，连续签到").append(consecutiveDays).append("天奖励：")
                    .append(consecutiveReward).append(" BT币");
        }

        if (milestoneReward > 0) {
            rewardDesc.append("，达成").append(consecutiveDays).append("天里程碑额外奖励：")
                    .append(milestoneReward).append(" BT币");

            // 记录里程碑
            recordMilestone(userId, "CONSECUTIVE_LOGIN_" + consecutiveDays,
                    (long) consecutiveDays, milestoneReward);
        }

        distributeBtCoins(userId, totalReward, rewardDesc.toString());

        // 更新活动进度
        int finalConsecutiveDays = consecutiveDays;
        updateActivityProgress(new UpdateActivityProgressBO() {{
            setUserId(userId);
            setActivityType(PermanentPromotionType.CONSECUTIVE_LOGIN.name());
            setProgressValue((long) finalConsecutiveDays);
            setIsIncrement(false);
        }});

        log.info("用户 {} 签到成功，连续签到 {} 天，获得 {} BT币", userId, consecutiveDays, totalReward);

        return buildCheckInVO(userId, checkIn, true);
    }

    @Override
    @Transactional
    public void updateActivityProgress(UpdateActivityProgressBO progressBO) {
        String userId = progressBO.getUserId();
        String activityType = progressBO.getActivityType();
        Long progressValue = progressBO.getProgressValue();

        QueryWrapper<UserActivityProgress> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId).eq("activity_type", activityType);
        UserActivityProgress progress = activityProgressMapper.selectOne(wrapper);

        if (progress == null) {
            progress = new UserActivityProgress();
            progress.setId(UUID.randomUUID().toString().replace("-", ""));
            progress.setUserId(userId);
            progress.setActivityType(activityType);
            progress.setCurrentValue(progressValue);
            progress.setLastUpdateTime(LocalDateTime.now());
            activityProgressMapper.insert(progress);
        } else {
            if (progressBO.getIsIncrement()) {
                progress.setCurrentValue(progress.getCurrentValue() + progressValue);
            } else {
                progress.setCurrentValue(progressValue);
            }
            progress.setLastUpdateTime(LocalDateTime.now());
            activityProgressMapper.updateById(progress);
        }

        // 检查里程碑
        checkAndRewardMilestone(userId, activityType, progress.getCurrentValue());
    }

    @Transactional
    public void checkAndRewardMilestone(String userId, String activityType, long currentValue) {
        // 根据活动类型检查相应的里程碑
        log.debug("检查用户 {} 的 {} 里程碑，当前值: {}", userId, activityType, currentValue);
    }


    @Override
    public UserCheckInVO getUserCheckInInfo(String userId) {
        LocalDate today = LocalDate.now();
        QueryWrapper<UserDailyCheckIn> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId).eq("check_in_date", today);
        UserDailyCheckIn todayCheckIn = checkInMapper.selectOne(wrapper);

        if (todayCheckIn != null) {
            return buildCheckInVO(userId, todayCheckIn, false);
        }

        // 获取最近一次签到
        QueryWrapper<UserDailyCheckIn> lastWrapper = new QueryWrapper<>();
        lastWrapper.eq("user_id", userId)
                .orderByDesc("check_in_date")
                .last("LIMIT 1");
        UserDailyCheckIn lastCheckIn = checkInMapper.selectOne(lastWrapper);

        return buildCheckInVO(userId, lastCheckIn, false);
    }

    @Override
    public List<CheckInCalendarVO> getCheckInCalendar(String userId, int year, int month) {
        YearMonth yearMonth = YearMonth.of(year, month);
        LocalDate startDate = yearMonth.atDay(1);
        LocalDate endDate = yearMonth.atEndOfMonth();

        // 查询该月的签到记录
        QueryWrapper<UserDailyCheckIn> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId)
                .between("check_in_date", startDate, endDate);
        List<UserDailyCheckIn> checkIns = checkInMapper.selectList(wrapper);

        Map<LocalDate, UserDailyCheckIn> checkInMap = checkIns.stream()
                .collect(Collectors.toMap(UserDailyCheckIn::getCheckInDate, c -> c));

        // 构建日历
        List<CheckInCalendarVO> calendar = new ArrayList<>();
        for (int day = 1; day <= yearMonth.lengthOfMonth(); day++) {
            LocalDate date = yearMonth.atDay(day);
            CheckInCalendarVO calendarVO = new CheckInCalendarVO();
            calendarVO.setDate(date);

            UserDailyCheckIn checkIn = checkInMap.get(date);
            if (checkIn != null) {
                calendarVO.setCheckedIn(true);
                calendarVO.setReward(checkIn.getReward());
            } else {
                calendarVO.setCheckedIn(false);
                calendarVO.setReward(0);
            }

            calendar.add(calendarVO);
        }

        return calendar;
    }

    // ========== 私有辅助方法 ==========

    private UserCheckInVO buildCheckInVO(String userId, UserDailyCheckIn checkIn, boolean justCheckedIn) {
        UserCheckInVO vo = new UserCheckInVO();
        vo.setUserId(userId);
        vo.setTodayDate(LocalDate.now());
        vo.setHasCheckedInToday(checkIn != null && checkIn.getCheckInDate().equals(LocalDate.now()));

        if (checkIn != null) {
            vo.setConsecutiveDays(checkIn.getConsecutiveDays());
            vo.setLastCheckInTime(checkIn.getCheckInTime());

            if (justCheckedIn) {
                vo.setTodayReward(checkIn.getReward());
            }
        } else {
            vo.setConsecutiveDays(0);
        }

        // 计算明天的预期奖励
        int nextConsecutiveDays = vo.getHasCheckedInToday() ?
                vo.getConsecutiveDays() + 1 : 1;
        int dailyReward = PermanentPromotionType.DAILY_LOGIN.getBaseReward();
        int consecutiveReward = PermanentPromotionType.calculateConsecutiveLoginReward(nextConsecutiveDays);
        int milestoneReward = PermanentPromotionType.getConsecutiveMilestoneReward(nextConsecutiveDays);
        vo.setTomorrowReward(dailyReward + consecutiveReward + milestoneReward);

        // 获取本月签到日历
        LocalDate today = LocalDate.now();
        vo.setMonthCalendar(getCheckInCalendar(userId, today.getYear(), today.getMonthValue()));

        return vo;
    }

    private void recordMilestone(String userId, String milestoneType, long achievedValue, int reward) {
        UserMilestoneRecord record = new UserMilestoneRecord();
        record.setId(UUID.randomUUID().toString().replace("-", ""));
        record.setUserId(userId);
        record.setMilestoneType(milestoneType);
        record.setAchievedValue(achievedValue);
        record.setReward(reward);
        record.setAchievedTime(LocalDateTime.now());
        userMilestoneRecordMapper.insert(record);

        log.info("用户 {} 达成里程碑 {}，获得 {} BT币", userId, milestoneType, reward);
    }

    private void distributeBtCoins(String userId, int amount, String description) {
        // 更新用户BT币余额
        UserExp userExp = userExpMapper.selectById(userId);
        if (userExp == null) {
            userExp = new UserExp();
            userExp.setId(userId);
            userExp.setBt(amount);
            userExpMapper.insert(userExp);
        } else {
            userExp.setBt(userExp.getBt() + amount);
            userExpMapper.updateById(userExp);
        }

        // 记录BT币变动
        BtTransaction transaction = new BtTransaction();
        transaction.setId(UUID.randomUUID().toString().replace("-", ""));
        transaction.setUserId(userId);
        transaction.setPoints(amount);
        transaction.setType("PERMANENT_PROMOTION");
        transaction.setRuleId("PERMANENT");
        transaction.setDescription(description);
        transaction.setCreatedTime(LocalDateTime.now());
        transactionMapper.insert(transaction);
    }

}
